package at.fhj.itm10.ticketmaster.beans;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;

import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
import java.util.Map;

import javax.annotation.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.context.FacesContext;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.apache.log4j.Logger;

/**
 * @author Kevin Reinmueller
 * @since November 2012
 */

@ManagedBean
@RequestScoped
public class OrderConfirmationBean {

	private final Logger logger = Logger.getLogger(OrderConfirmationBean.class);

	private String tx = null;
	private FacesContext context;
	private Map<String, String> paramMap;
	
	/**
	 * paramMap for fetching requestparameters
	 * tx confiramtion key from PayPal
	 */
	public OrderConfirmationBean() {
		// get tx GET-URL-parameter
		context = FacesContext.getCurrentInstance();
		paramMap = context.getExternalContext().getRequestParameterMap();
		tx = paramMap.get("tx");
	}

	/**
	 * finalize order checks if order is payed (with paypal) writes order in
	 * database and empties the cart
	 * 
	 * @return BOOLEAN
	 */
	public boolean finalizeOrder() {
		logger.debug("finalizeOrder()");

		Boolean ret;

		if (tx != null)
			ret = this.checkIfPaid(tx);
		else
			ret = false;

		return ret;
	}

	/**
	 * checkIfPaid checks via PayPal PDT if order is correctly paid
	 * 
	 * TrustManager to bypass SSL check
	 * 
	 * @param String
	 *            
	 * @return BOOLEAN
	 */
	private boolean checkIfPaid(String tx) {
		logger.debug("checkIfPaid()");

		Boolean ret = false;
		URL url = null;
		URLConnection urlConn = null;

		DataOutputStream cgiInput = null;
		OutputStream outStr = null;

		// init trustmanager
		TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
			public java.security.cert.X509Certificate[] getAcceptedIssuers() {
				return null;
			}

			public void checkClientTrusted(X509Certificate[] certs,
					String authType) {
			}

			public void checkServerTrusted(X509Certificate[] certs,
					String authType) {
			}
		} };

		// Install the all-trusting trust manager
		SSLContext sc = null;

		try {
			sc = SSLContext.getInstance("SSL");
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
			logger.debug("problem during setup of SSL connection", e);
		}

		try {
			sc.init(null, trustAllCerts, new java.security.SecureRandom());
		} catch (KeyManagementException e) {
			e.printStackTrace();
			logger.debug("problem during setup of SSL initialization", e);

		}

		HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());

		// Create all-trusting host name verifier
		HostnameVerifier allHostsValid = new HostnameVerifier() {
			public boolean verify(String hostname, SSLSession session) {
				return true;
			}
		};

		// Install the all-trusting host verifier
		HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);

		// URL of target page script.
		// https://sandbox.paypal.com/cgi-bin/webscr

		try {
			url = new URL("https://sandbox.paypal.com/cgi-bin/webscr");
		} catch (MalformedURLException e) {
			e.printStackTrace();
			logger.debug(
					"problem with url 'https://sandbox.paypal.com/cgi-bin/webscr'",
					e);

		}
		try {
			urlConn = url.openConnection();
		} catch (IOException e) {
			e.printStackTrace();
			logger.debug("problem opening connection", e);

		}
		urlConn.setDoInput(true);
		urlConn.setDoOutput(true);
		urlConn.setUseCaches(false);
		urlConn.setRequestProperty("Content-Type",
				"application/x-www-form-urlencoded");

		try {
			outStr = urlConn.getOutputStream();
		} catch (IOException e) {
			e.printStackTrace();
			logger.debug("problem receiving output stream of connection", e);
		}
		// Send POST output.
		cgiInput = new DataOutputStream(outStr);

		String content = null;
		try {
			content = "tx="
					+ URLEncoder.encode(tx, "UTF-8")
					+ "&cmd="
					+ URLEncoder.encode("_notify-synch", "UTF-8")
					+ "&at="
					+ URLEncoder
							.encode("AZESR62zqA6mFvTErHtScbstjvHybjUaSlrkIFcR64-B48iRXSRFhlmCSXq",
									"UTF-8");

			cgiInput.writeBytes(content);
		} catch (IOException e) {
			e.printStackTrace();
			logger.debug("problem encoding url", e);

		}
		try {
			cgiInput.flush();
		} catch (IOException e) {
			e.printStackTrace();
			logger.debug("problem flushing cgiInput", e);

		}
		try {
			cgiInput.close();
		} catch (IOException e) {
			e.printStackTrace();
			logger.debug("problem closing cgiInput", e);
		}
		try {
			outStr.close();
		} catch (IOException e) {
			e.printStackTrace();
			logger.debug("problem closing outStr", e);

		}

		// reads the CGI response and print it inside the servlet content
		BufferedReader cgiOutput = null;
		InputStreamReader inpStr = null;
		InputStream secInpStr = null;
		try {
			secInpStr = urlConn.getInputStream();
		} catch (IOException e1) {
			e1.printStackTrace();
			logger.debug("problem getting urlConn Input stream", e1);

		}
		try {
			inpStr = new InputStreamReader(secInpStr, "UTF8");
		} catch (UnsupportedEncodingException e1) {
			logger.debug("problem initializing InputStreamReader", e1);
			e1.printStackTrace();
		}
		cgiOutput = new BufferedReader(inpStr);
		try {
			cgiOutput.readLine();
		} catch (IOException e) {
			logger.debug("problem readingLine of cgiOutput", e);
			e.printStackTrace();
		}
		String line = null;
		try {
			while (null != (line = cgiOutput.readLine())) {
				String[] splitArr = line.split("=");

				if (splitArr.length > 1) {
					// System.out.println(splitArr[0] + splitArr[1]);
					if (splitArr[0].equals("payment_status")
							&& splitArr[1].equals("Completed")) {
						ret = true;
					}
				}
			}
		} catch (IOException e) {
			logger.debug("problem cgiOutput writing output of cgiOutput to array", e);
			e.printStackTrace();
		}
		try {
			cgiOutput.close();
		} catch (IOException e) {
			logger.debug("problem closing cgiOutput", e);
			e.printStackTrace();
		}
		return ret;
	}
}